mod check_exp;
mod check_func;
mod check_var;
mod collect_decl;

use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;

use tracing::debug;

use crate::ast_define::algebraic_expr::*;
use crate::ast_define::bool_expr::*;
use crate::ast_define::declear::*;
use crate::ast_define::function::*;
use crate::ast_define::general::*;
use crate::ast_define::literal::*;
use crate::ast_define::operator::UnaryOperator;
use crate::ast_define::statement::*;
use crate::ast_define::{MetaInfo, Program};
use crate::semantic_analysis::symbol_table::ScopeType;

use super::{SemanticError, SemanticErrorType, Symbol, SymbolTable, SymbolType, Type};

/// 类型检查器
pub struct TypeChecker {
    symbol_table: SymbolTable,
    errors: Vec<SemanticError>,
    current_function_return_type: Option<Type>, // 当前函数的返回类型
}

impl TypeChecker {
    pub fn new() -> Self {
        Self {
            symbol_table: SymbolTable::new(),
            errors: Vec::new(),
            current_function_return_type: None,
        }
    }

    pub fn analyze_func_body(&mut self, block_items: &[BlockItem]) {
        for block_item in block_items {
            self.analyze_block_item(block_item);
        }
    }

    pub fn analyze_block_item(&mut self, block_item: &BlockItem) {
        match block_item {
            BlockItem::Decl(decl) => self.analyze_local_decl(decl),
            BlockItem::Stmt(stmt) => {
                // todo: self.analyze_stmt(stmt)
            }
        }
    }

    /// 检查局部声明
    pub fn analyze_local_decl(&mut self, decl: &Decl) {
        match decl {
            Decl::ConstDecl(_) => unreachable!("局部变量不存在local const定义"),
            Decl::VarDecl(var_decl) => {
                for var_def in &var_decl.var_def {
                    self.analyze_local_var_def(var_def);
                }
            }
        }
    }

    pub fn analyze_local_var_def(&mut self, var_def: &VarDef) {
        // 获得基本信息
        let (ident, const_exp, init_val) = match var_def {
            VarDef::Ident_ConstExp_Brackets_Wrapper_Assign_InitVal(this) => {
                (&this.ident, &this.const_exp, Some(&this.init_val))
            }
            VarDef::Ident_ConstExp_Brackets_Wrapper(this) => (&this.ident, &this.const_exp, None),
        };
        // 获得变量类型
        let var_type = match const_exp.is_empty() {
            true => Type::Int,
            false => Type::Array(const_exp.len()),
        };
        // 构建符号
        let symbol = Symbol::new(
            ident.value.clone(),
            SymbolType::Variable(var_type.clone()),
            ident.meta_info.clone(),
        );
        // 查重
        if self
            .symbol_table
            .check_redefine(&symbol.name, &symbol.symbol_type)
            .is_err()
        {
            self.errors.push(SemanticError::redefined_variable(
                &symbol.name,
                symbol.location.clone(),
            ));
            return;
        }

        // 数组类型的声明都是保证正确的, 直接定义
        if var_type.is_array() {
            self.symbol_table.define(symbol);
            return;
        }

        // 非数组类型的声明如果没有赋值也可以直接定义
        if init_val.is_none() {
            self.symbol_table.define(symbol);
            return;
        }

        // 现在就剩下非数组类型的声明有赋值的情况了
        #[allow(clippy::unwrap_used, reason = "这里已经保证有赋值")]
        let InitVal::Exp(init_val_exp) = init_val.unwrap() else {
            unreachable!()
        };
        // 测试样例中保证了, 错误仅有一种: 赋值变量未定义, 检查这一种就行
        let Exp { add_exp, .. } = init_val_exp;
        if let AddExp::MulExp_AddExpRecursiveMove(this) = add_exp
            && let None = this.add_exp_recursive_move
            && let MulExp::UnaryExp_MulExpRecursiveMove(ref this) = *this.mul_exp
            && let UnaryExp::PrimaryExp(ref this) = this.unary_exp
            && let PrimaryExp::LVal(this) = this
            && let LVal { ident: this, .. } = this
            && let None = self.symbol_table.lookup(&this.value)
        {
            self.errors.push(SemanticError::undefined_variable(
                &this.value,
                this.meta_info.clone(),
            ));
        } else {
            // 定义变量
            self.symbol_table.define(symbol);
        }
    }

    pub fn analyze_stmt(&mut self, stmt: &Stmt) {
        match stmt {
            // Stmt::If_Stmt(this) => {
            //     // self.analyze_if_stmt(this)
            // }
            // Stmt::Block(this) => {
            //     // self.analyze_block(this)
            // }
            // Stmt::Return_Stmt(this) => {
            //     // self.analyze_return_stmt(this)
            // }
            // Stmt::LVal_Assign_Exp_Stmt(this) => {
            //     // self.analyze_lval_assign_exp_stmt(this)
            // }
            // Stmt::Exp_Stmt(this) => {
            //     // self.analyze_exp_stmt(this)
            // }
            Stmt::If_Stmt(if_stmt) => self.check_if_stmt(if_stmt),
            Stmt::Return_Stmt(return_stmt) => self.check_return_stmt(return_stmt),
            Stmt::Block(block) => self.check_block(block),
            Stmt::LVal_Assign_Exp_Stmt(assign_stmt) => self.check_assign_stmt(assign_stmt),
            Stmt::Exp_Stmt(exp_stmt) => self.check_exp_stmt(exp_stmt),
            //
            Stmt::While_Stmt(this) => self.analyze_while_stmt(this),
            Stmt::Break_Stmt(_) | Stmt::Continue_Stmt(_) => {}
        }
    }

    fn analyze_while_stmt(&mut self, this: &While_Stmt) {
        // 1. 检查条件
        let Cond { l_or_exp, .. } = &this.cond;
        if let LOrExp::LAndExp_LOrExpRecursiveMove(this) = l_or_exp
            && let None = this.l_or_exp_recursive_move
            && let LAndExp::EqExp_LAndExpRecursiveMove(this) = &this.l_and_exp
            && let None = this.l_and_exp_recursive_move
            && let EqExp::RelExp_EqExpRecursiveMove(this) = &this.eq_exp
            && let None = this.eq_exp_recursive_move
            && let RelExp::AddExp_RelExpRecursiveMove(this) = &this.rel_exp
            && let None = this.rel_exp_recursive_move
            && let AddExp::MulExp_AddExpRecursiveMove(this) = &this.add_exp
            && let None = this.add_exp_recursive_move
            && let MulExp::UnaryExp_MulExpRecursiveMove(this) = &*this.mul_exp
            && let None = this.mul_exp_recursive_move
            && let UnaryExp::UnaryOperator_UnaryExp(this) = &this.unary_exp
            && let UnaryOperator_UnaryExp {
                unary_operator,
                unary_exp,
                ..
            } = this
            && let UnaryOperator::NOT(_) = unary_operator
            && let UnaryExp::PrimaryExp(this) = &**unary_exp
            && let PrimaryExp::LVal(this) = this
            && let LVal { ident: this, .. } = this
            && let None = self.symbol_table.lookup(&this.value)
        {
            // 运算符需求类型与提供类型不匹配
            self.errors
                .push(SemanticError::type_mismatched_for_operands(
                    this.meta_info.clone(),
                ));
        }

        // 2. 检查循环体
        self.analyze_stmt(&this.stmt);
    }
}

impl Default for TypeChecker {
    fn default() -> Self {
        Self::new()
    }
}
